home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / alloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-15  |  9.3 KB  |  351 lines

  1. #ifndef lintdif
  2.  
  3. #ifndef NO_Sid = "$Id: alloc.c,v 1.1.1.2 1998/04/15 19:21:56 lhecking Exp $";
  4. #endif
  5.  
  6. /* GNUPLOT - alloc.c */
  7.  
  8. /*[
  9.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  10.  *
  11.  * Permission to use, copy, and distribute this software and its
  12.  * documentation for any purpose with or without fee is hereby granted,
  13.  * provided that the above copyright notice appear in all copies and
  14.  * that both that copyright notice and this permission notice appear
  15.  * in supporting documentation.
  16.  *
  17.  * Permission to modify the software is granted, but not the right to
  18.  * distribute the complete modified source code.  Modifications are to
  19.  * be distributed as patches to the released version.  Permission to
  20.  * distribute binaries produced by compiling modified sources is granted,
  21.  * provided you
  22.  *   1. distribute the corresponding source modifications from the
  23.  *    released version in the form of a patch file along with the binaries,
  24.  *   2. add special version identification to distinguish your version
  25.  *    in addition to the base release version number,
  26.  *   3. provide your name and address as the primary contact for the
  27.  *    support of your modified version, and
  28.  *   4. retain our contact information in regard to use of the base
  29.  *    software.
  30.  * Permission to distribute the released version of the source code along
  31.  * with corresponding source modifications in the form of a patch file is
  32.  * granted with same provisions 2 through 4 for binary distributions.
  33.  *
  34.  * This software is provided "as is" without express or implied warranty
  35.  * to the extent permitted by applicable law.
  36. ]*/
  37.  
  38. /*
  39.  * AUTHORS
  40.  *
  41.  * Alexander Lehmann (collected functions from misc.c and binary.c)
  42.  *
  43.  */
  44.  
  45. #include "plot.h" /* includes "alloc.h" */
  46.  
  47. #if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286)
  48. #include <alloc.h>        /* for farmalloc, farrealloc */
  49. #endif
  50.  
  51. #if defined(_Windows) && !defined(WIN32)
  52. #include <windows.h>
  53. #include <windowsx.h>
  54. #define farmalloc(s) GlobalAllocPtr(GHND,s)
  55. #define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND)
  56. #endif
  57.  
  58. #ifndef NO_GIH
  59. #include "help.h"
  60. #endif
  61.  
  62. #ifndef GP_FARMALLOC
  63. # ifdef FARALLOC
  64. #  define GP_FARMALLOC(size) farmalloc ((size))
  65. #  define GP_FARREALLOC(p,size) farrealloc ((p), (size))
  66. # else
  67. #  define GP_FARMALLOC(size) malloc ((size_t)(size))
  68. #  define GP_FARREALLOC(p,size) realloc ((p), (size_t)(size))
  69. # endif
  70. #endif
  71.  
  72. /* uncomment if you want to trace all allocs */
  73. #define TRACE_ALLOC(x) /*printf x*/
  74.  
  75.  
  76. #ifdef CHECK_HEAP_USE
  77.  
  78. /* This is in no way supported, and in particular it breaks the
  79.  * online help. But it is useful to leave it in in case any
  80.  * heap-corruption bugs turn up. Wont work with FARALLOC
  81.  */
  82.  
  83. struct frame_struct {
  84.     char *use;
  85.     int requested_size;
  86.     int pad; /* preserve 8-byte alignment */
  87.     int checksum;
  88. };
  89.  
  90. struct leak_struct {
  91.     char *file;
  92.     int line;
  93.     int allocated;
  94. };
  95.  
  96. static struct leak_struct leak_stack[40];  /* up to 40 nested leak checks */
  97. static struct leak_struct *leak_frame = leak_stack;
  98.  
  99. static long bytes_allocated = 0;
  100.  
  101. #define RESERVED_SIZE sizeof(struct frame_struct)
  102. #define CHECKSUM_INT 0xcaac5e1f
  103. #define CHECKSUM_FREE 0xf3eed222
  104. #define CHECKSUM_CHAR 0xc5
  105.  
  106. static void mark(p, size, usage)
  107. struct frame_struct *p;
  108. unsigned long size;
  109. char *usage;
  110. {
  111.     p->use = usage;
  112.     p->requested_size = size;
  113.     p->checksum = (CHECKSUM_INT ^ (int)(p->use) ^ size);
  114.     ((unsigned char *)(p+1))[size] = CHECKSUM_CHAR;
  115. }
  116.  
  117. #define mark_free(p) ( ((struct frame_struct *)p)[-1].checksum = CHECKSUM_FREE)
  118.     
  119. static void validate(x)
  120. void *x;
  121. {
  122.     struct frame_struct *p = (struct frame_struct *)x - 1;
  123.     if (p->checksum != (CHECKSUM_INT ^ (int)(p->use) ^ p->requested_size))
  124.     {
  125.         fprintf(stderr, "Heap corruption at start of block for %s\n", p->use);
  126.         if (p->checksum == CHECKSUM_FREE)
  127.             fprintf(stderr, "Looks like it has already been freed ?\n");
  128.         abort();
  129.     }
  130.  
  131.     if ( ((unsigned char *)(p+1))[p->requested_size] != CHECKSUM_CHAR)
  132.     {
  133.         fprintf(stderr, "Heap corruption at end of block for %-60s\n", p->use);
  134.         int_error("Argh !", NO_CARET);
  135.     }
  136. }        
  137.  
  138. /* used to confirm that a pointer is inside an allocated region via
  139.  * macro CHECK_POINTER. Nowhere near as good as using a bounds-checking
  140.  * compiler (such as gcc-with-bounds-checking), but when we do
  141.  * come across problems, we can add these guards to the code until
  142.  * we find the problem, and then leave the guards in (as CHECK_POINTER
  143.  * macros which expand to nothing, until we need to re-enable them)
  144.  */
  145.  
  146. void check_pointer_in_block(void *block, void *p, int size, char *file, int line)
  147. {
  148.     struct frame_struct *f = (struct frame_struct *)block - 1;
  149.     validate(block);
  150.     if (p < block || p >= (block + f->requested_size))
  151.     {
  152.         fprintf(stderr, "argh - pointer %p outside block %p->%p for %s at %s:%d\n",
  153.           p, block, (char *)block + f->requested_size, f->use, file, line);
  154.         int_error("argh - pointer misuse !", NO_CARET);
  155.     }
  156. }
  157.  
  158. char *gp_alloc(size, usage)
  159. unsigned long size;
  160. char *usage;
  161. {
  162.     struct frame_struct *p;
  163.     unsigned long total_size = size + RESERVED_SIZE + 1;
  164.     
  165.     TRACE_ALLOC(("gp_alloc %d for %s\n", (int) size, usage?usage:"<unknown>"));
  166.     
  167.     p=malloc(total_size);
  168.     if (!p) int_error("Out of memory", NO_CARET);
  169.  
  170.     bytes_allocated += size;
  171.     
  172.     mark(p,size,usage);
  173.     
  174.     return (char *)(p+1);
  175. }
  176.  
  177. generic *gp_realloc(old, size, usage)
  178. generic *old;
  179. unsigned long size;
  180. char *usage;
  181. {
  182.     if (!old) return gp_alloc(size, usage);
  183.     validate(old);
  184.     mark_free(old); /* if block gets moved, old block is marked free */
  185.                     /* if not, we'll remark it later */
  186.  
  187.     
  188.     {
  189.         struct frame_struct *p = (struct frame_struct *)old - 1;
  190.         unsigned long total = size + RESERVED_SIZE + 1;
  191.  
  192.         p = realloc(p, total);
  193.  
  194.         if (!p) int_error("Out of memory", NO_CARET);
  195.  
  196.         TRACE_ALLOC(("gp_realloc %d for %s (was %d)\n",
  197.           (int)size, usage?usage:"<unknown>", p->requested_size));
  198.  
  199.         bytes_allocated += size - p->requested_size;
  200.         
  201.         mark(p,size,usage);
  202.  
  203.         return (generic *)(p+1);
  204.     }
  205. }
  206.  
  207. #undef free
  208.  
  209. void checked_free(p)
  210. void *p;
  211. {
  212.     validate(p);
  213.     mark_free(p);  /* trap attempts to free twice */
  214.     TRACE_ALLOC(("free %d for %s\n",
  215.       ((struct frame_struct *)p - 1)->requested_size,
  216.       ((struct frame_struct *)p - 1)->use));
  217.     bytes_allocated -= ((struct frame_struct *)p - 1) -> requested_size;
  218.     free( (struct frame_struct *) p - 1);
  219. }
  220.  
  221.  
  222. /* this leak checking stuff will be broken by first int_error or interrupt */
  223.  
  224. void start_leak_check(char *file, int line)
  225. {
  226.     if (leak_frame >= leak_stack+40)
  227.     {
  228.         fprintf(stderr, "too many nested memory-leak checks - %s:%d\n", file, line);
  229.         return;
  230.     }
  231.  
  232.     leak_frame->file = file;
  233.     leak_frame->line = line;
  234.     leak_frame->allocated = bytes_allocated;
  235.  
  236.     ++leak_frame;
  237. }
  238.  
  239. void end_leak_check(char *file, int line)
  240. {
  241.     if (--leak_frame < leak_stack)
  242.     {
  243.         fprintf(stderr, "memory-leak stack underflow at %s:%d\n", file, line);
  244.         return;
  245.     }
  246.  
  247.     if (leak_frame->allocated != bytes_allocated)
  248.     {
  249.         fprintf(stderr, "net change of %+d heap bytes between %s:%d and %s:%d\n",
  250.             (int)(bytes_allocated - leak_frame->allocated),
  251.             leak_frame->file, leak_frame->line, file, line);
  252.     }
  253. }
  254.  
  255. #else  /* CHECK_HEAP_USE */
  256.  
  257. /* gp_alloc:
  258.  * allocate memory 
  259.  * This is a protected version of malloc. It causes an int_error 
  260.  * if there is not enough memory, but first it tries FreeHelp() 
  261.  * to make some room, and tries again. If message is NULL, we 
  262.  * allow NULL return. Otherwise, we handle the error, using the
  263.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  264.  * so it depends on this using malloc().
  265.  */
  266.  
  267. char *
  268. gp_alloc(size, message)
  269.     unsigned long size;        /* # of bytes */
  270.     char *message;            /* description of what is being allocated */
  271. {
  272.     char *p;                /* the new allocation */
  273.     char errbuf[100];        /* error message string */
  274.  
  275. #ifndef NO_GIH
  276.     p = GP_FARMALLOC(size);
  277.     if (p == (char *)NULL) {
  278.        FreeHelp();            /* out of memory, try to make some room */
  279. #endif /* NO_GIH */
  280.        p = GP_FARMALLOC(size);    /* try again */
  281.        if (p == (char *)NULL) {
  282.           /* really out of memory */
  283.           if (message != NULL) {
  284.              (void) sprintf(errbuf, "out of memory for %s", message);
  285.              int_error(errbuf, NO_CARET);
  286.              /* NOTREACHED */
  287.           }
  288.           /* else we return NULL */
  289.        }
  290. #ifndef NO_GIH
  291.     }
  292. #endif
  293.     return(p);
  294. }
  295.  
  296. /*
  297.  * note gp_realloc assumes that failed realloc calls leave the original mem block
  298.  * allocated. If this is not the case with any C compiler, a substitue
  299.  * realloc function has to be used.
  300.  */
  301.  
  302. generic *
  303. gp_realloc(p, size, message)
  304.     generic *p;            /* old mem block */
  305.     unsigned long size;        /* # of bytes */
  306.     char *message;            /* description of what is being allocated */
  307. {
  308.     char *res;                /* the new allocation */
  309.     char errbuf[100];        /* error message string */
  310.  
  311.     /* realloc(NULL,x) is meant to do malloc(x), but doesn't always */
  312.     if (!p)
  313.     return gp_alloc(size,message);
  314.  
  315. #ifndef NO_GIH
  316.     res = GP_FARREALLOC(p,size);
  317.     if (res == (char *)NULL) {
  318.        FreeHelp();            /* out of memory, try to make some room */
  319. #endif /* NO_GIH */
  320.        res = GP_FARREALLOC(p,size);    /* try again */
  321.        if (res == (char *)NULL) {
  322.           /* really out of memory */
  323.           if (message != NULL) {
  324.              (void) sprintf(errbuf, "out of memory for %s", message);
  325.              int_error(errbuf, NO_CARET);
  326.              /* NOTREACHED */
  327.           }
  328.           /* else we return NULL */
  329.        }
  330. #ifndef NO_GIH
  331.     }
  332. #endif
  333.     return(res);
  334. }
  335.  
  336. #endif /* CHECK_HEAP_USE */
  337.  
  338. #ifdef FARALLOC
  339. void gpfree(p)
  340. generic *p;
  341. {
  342. #ifdef _Windows
  343. HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
  344.     GlobalUnlock(hGlobal);
  345.     GlobalFree(hGlobal);
  346. #else
  347.     farfree(p);
  348. #endif
  349. }
  350. #endif
  351.